#include "parse.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <boost/regex.hpp>

using namespace std;

void cget::parse(int argc,char *argv[],Config& c) throw(string) {
	parse_file(c);
	parse_cmdline(argc,argv,c);
	parse_url(c);
}

void cget::parse_cmdline(int argc,char *argv[],Config& c) throw(string) {
	int i;

#define SET_OPTION(sub,op,op_sh,value)	\
		if(sub == op_sh) {			\
			c.setConfig(op,value);	\
			continue;		\
		}
	
#define SET_OPTION_ARG(sub,op,op_sh) 	\
		if(sub == op_sh) {			\
			if(i == (argc-1))	\
				throw string("option error");	\
								\
			c.setConfig(op,argv[i+1]);		\
			++i;					\
			continue;				\
		}

	for(i = 1; i < argc; ++i) {
		string par(argv[i]);
		if(par.at(0) == '-') {
			string sub(par.substr(1));

			SET_OPTION(sub,c_version,c_version_sh,c_on);
			SET_OPTION(sub,c_help,c_help_sh,c_on);
			SET_OPTION(sub,c_debug,c_debug_sh,c_on);
			SET_OPTION(sub,c_continue,c_continue_sh,c_on);

			SET_OPTION_ARG(sub,c_proxy,c_proxy_sh);
			SET_OPTION_ARG(sub,c_tries,c_tries_sh);
			SET_OPTION_ARG(sub,c_waitretry,c_waitretry_sh);
			SET_OPTION_ARG(sub,c_maxspeed,c_maxspeed_sh);
			SET_OPTION_ARG(sub,c_minspeed,c_minspeed_sh);
			SET_OPTION_ARG(sub,c_threads,c_threads_sh);

			ostringstream error_stream;
			error_stream << "unknown option:" << par;

			throw error_stream.str();
			/*
			if(par.substr(1) == c_proxy_sh) {
				if(i == (argc-1))
					throw string("argument error");

				c.setConfig(c_proxy,argv[i+1]);
				continue;
			}
			*/
		}
		else {
			c.setConfig(c_url,argv[i]);		
		}
	}
}

void cget::parse_file(Config& c) throw(string) {
	/*
	ostringstream os;
	os << "hello ";
	os << 1;
	throw os.str();
	*/
	string line;
	ifstream conf_stream(cget::config_file,ios::in|ios::binary);
	
	while(getline(conf_stream,line)) {
		if(line.length() == 0 || line.at(0) == '#')
			continue;

		istringstream line_stream(line);
		string key;
		string value;
		line_stream >> key >> value;

		c.setConfig(key,value);
	}
}

void cget::parse_url(Config& c) throw(string) {
	//boost::regex re("");
	string url = c.getConfig(c_url);

	//cout << "url###(" << url << ")" << endl;
	if(url.length() == 0) {
		throw string("url error");
	}
	
	boost::regex re("(http(s?)|ftp)://(([a-zA-Z0-9]+):([a-zA-Z0-9]+)@)?(([-a-zA-Z0-9]+\\.)+([-a-zA-Z0-9]+))(:([0-9]+))?(/.*)?");
	boost::smatch m;

	if(boost::regex_match(url,m,re)) {
		
		c.setConfig(c_protocol,m[1]);
		c.setConfig(c_username,m[4]);
		c.setConfig(c_password,m[5]);
		c.setConfig(c_host,m[6]);
		c.setConfig(c_port,m[10]);

		string path(m[11].first,m[11].second);
		if(path.length() == 0) {
			c.setConfig(c_path,"/index.html");
			c.setConfig(c_filename,"index.html");
		}
		else if(*path.rbegin() == '/') {
			c.setConfig(c_path,path+"index.html");
			c.setConfig(c_filename,"index.html");
		}
		else {
			size_t filename_pos = path.find_last_of('/');
			c.setConfig(c_path,path);
			c.setConfig(c_filename,path.substr(filename_pos+1));
		}

		/*
		for(size_t i = 1; i < m.size(); ++i) {
			cout << i << " - " << m[i] << endl;
		}
		*/
	}
	else {
		throw string("url error");
	}


}
